﻿using UnityEngine;
using System.Collections.Generic;
using Dict.DataModel;
using ProtoBuf.Message;

namespace Room
{
    public class RoomCharactorManager
    {

        public delegate void EventCharactorStartHandler(RoomCharactor charactor);
        public delegate void EventCharactorStopHandler(RoomCharactor charactor);

        /// <summary>
        /// 在一个新的角色加入到场景中时调用
        /// </summary>
        public event EventCharactorStartHandler onCharactorStartCallback;

        /// <summary>
        /// 在一个角色被从场景中移除时调用
        /// </summary>
        public event EventCharactorStopHandler onCharactorStopCallback;

        public RoomBase room;

        private Dictionary<string, RoomCharactor> charactors = new Dictionary<string, RoomCharactor>();
        private bool running = false;
        
        public bool Running
        {
            get
            {
                return running;
            }
        }

        public void Tick()
        {
            var enumerator = charactors.GetEnumerator();

            while (enumerator.MoveNext())
            {
                var charactor = enumerator.Current.Value;
                charactor.Tick();
            }
           
        }
        public void LateTick()
        {
            var enumerator = charactors.GetEnumerator();
            while (enumerator.MoveNext())
            {
                var charactor = enumerator.Current.Value;
                charactor.LateTick();
            }
        }

        public void Pause()
        {
            if (running)
            {
                running = false;
                foreach (var tmp in charactors)
                {
                    tmp.Value.DoPause();
                }
            }
        }
        public void Resume()
        {
            if (!running)
            {
                running = true;
                foreach (var tmp in charactors)
                {
                    tmp.Value.DoResume();
                }
            }
        }

        public void ClearAll()
        {
            var enumerator = charactors.GetEnumerator();
            while (enumerator.MoveNext())
            {
                DestroyCharactor(enumerator.Current.Key);
                enumerator = charactors.GetEnumerator();
            }
        }

        public void HideOtherPlayer()
        {
            ClearOther();
            return;
        }

        
        public void ClearOther()
        {
            List<string> keys = new List<string>();
            foreach (var pair in charactors)
            {
                if (pair.Value.type==CharactorType.OtherPlayer)
                {
                    keys.Add(pair.Key);
                }
            }
            foreach (var key in keys)
            {
                DestroyCharactor(key);
            }
        }

        public Dictionary<string, RoomCharactor> GetCharactors()
        {
            return charactors;
        }

        public RoomCharactor GetCharactor(string id)
        {
            if (charactors.ContainsKey(id))
            {
                return charactors[id];
            }
            return null;
        }
        string selfId = "";

        public string GetSelfId()
        {
            return selfId;
        }

        public RoomCharactor GetSelfCharactor()
        {
            if (charactors.ContainsKey(selfId))
            {
                return charactors[selfId];
            }
            return null;
        }
        public void MoveTo(string id, Vector3 to)
        {
            var charactor = GetCharactor(id);
            if (charactor != null)
            {
                charactor.MoveTo(to);
            }
        }
        public void StopTo(string id, Vector3 to)
        {
            var charactor = GetCharactor(id);
            if (charactor != null)
            {
                charactor.StopTo(to);
            }
        }
        public void SetPosition(string id, Vector3 pos)
        {
            var charactor = GetCharactor(id);
            if (charactor != null)
            {
                charactor.transform.position = pos;
            }
        }
        public Vector3 GetPosition(string id)
        {
            var charactor = GetCharactor(id);
            if (charactor != null)
            {
                return charactor.transform.position;
            }
            return Vector3.zero;
        }

        #region create


       
        public void CreateSelfPlayer(string id, string heroId, string weaponId, string name,string title,string unionName,int serverID, float angle = 0f)//...
        {
            selfId = id;

            RoomCharactor charactor = CreateCharactor(id, CharactorType.SelfPlayer);
            charactor.transform.localEulerAngles = new Vector3(0, angle, 0);
            charactor.Reset(AIType.Self, LODType.Player, MoveType.Navigation, UIType.Player);
            charactor.gameObject.AddComponent<SceneMainActor>();

            var ui = charactor.ui as RCUIPlayer;
            
            ui.Init(name, title, unionName,serverID);
            ui.SetColor(new Color((float)0xff / (float)0xff, (float)0xe3 / (float)0xff, (float)0x24 / (float)0xff));

            var lod = charactor.lod as RCLODPlayer;
            lod.Init(heroId, weaponId);

            var ai = charactor.ai as RCAIActor;
            ai.height = (float)Dict.Blo.DictHeroBlo.GetTableHero(heroId).Height ;
            ai.hpOffest = (float)Dict.DictDataManager.Instance.tableGameConfigureDao.currentData.FieldSelfHpHeight;
            

            ManagerController.Instance.cameraTool.SetMainPlayer(charactor.transform);
            DoCharactorStart(charactor);
        }

       /// <summary>
       /// 宠物
       /// </summary>
       /// <param name="pet"></param>
        public void CreatePet(string petId,string masterId)
        {
            var pet = Dict.Blo.DictPetBlo.GetTablePet(petId);
            var master = GetCharactor(masterId);
            RoomCharactor charactor = CreateCharactor(petId, CharactorType.Pet);
            charactor.Reset(AIType.Pet, LODType.Pet, MoveType.Navigation, UIType.None);
            

            var lod = charactor.lod as RCLODPet;
            lod.Init(petId);


            var ai = charactor.ai as RCAIPet;
            ai.Init(pet, master);

            
            var move = charactor.move as RCMoveNavigation;
            move.SetSpeed(5f);
            
            DoCharactorStart(charactor);
        }


		public RoomCharactor CreateOtherPlayer(string id, string heroId, string nickname,string equipId, string title,
			string unionName,int serverID,bool canClick=false)//...
        {
            //string model;
            //var dict = Dict.DictDataManager.Instance.tableHeroDao.GetById(heroId);
            //model = dict.resName;

            RoomCharactor charactor = CreateCharactor(id, CharactorType.OtherPlayer);
            charactor.Reset(AIType.OtherPlayer, LODType.Player, MoveType.Navigation, UIType.Player);

            //charactor.SetKillNum(killNum);

            var ui = charactor.ui as RCUIPlayer;
			ui.Init(nickname,title,unionName,serverID);
            ui.SetColor(Color.white);

            var lod = charactor.lod as RCLODPlayer;
            lod.Init(heroId, equipId);

            //charactor.SetKillNum(killNum);
            var ai = charactor.ai as RCAIActor;
            ai.height = (float)Dict.Blo.DictHeroBlo.GetTableHero(heroId).Height;
            ai.hpOffest = (float)Dict.DictDataManager.Instance.tableGameConfigureDao.currentData.FieldOtherHpHeight;
            DoCharactorStart(charactor);

            return charactor;
        }

       

       
        
        /// <summary>
        /// 宝箱盒子
        /// </summary>
        /// <param name="boxId"></param>
        public void CreateBox(ProtoBuf.Message.CopyBoxInfo box)
        {
            RoomCharactor charactor = CreateCharactor(box.boxId, CharactorType.Box);
            charactor.Reset(AIType.Box, LODType.Box, MoveType.Fixed, UIType.Box);
            var ui = charactor.ui as RCUIBox;
            ui.Init(box.boxId);

            var move = charactor.move as RCMoveFixed;
            move.Init(new Vector3((float)box.x, (float)box.y, (float)box.z),(float)box.angle);

            var ai = charactor.ai as RCAIBox;
            ai.Init(box.boxId,box.isOpen);

            var lod = charactor.lod as RCLODBox;
            lod.Init(box.res);
            DoCharactorStart(charactor);
            charactor.gameObject.AddComponent<BoxCollider>();
        }

        #region 公会战

        public void CreateUnionSelfPlayer(ProtoBuf.Message.InstUFPlayer player)
        {
            var id = player.guid+"";
            var heroId = player.heroId;
            var weaponId = player.weaponId;
            var name = player.nickName;
            var angle = 0;
            selfId = id;

            RoomCharactor charactor = CreateCharactor(id, CharactorType.UnionFightSelf);
            charactor.transform.localEulerAngles = new Vector3(0, angle, 0);
            charactor.Reset(AIType.UnionSelf, LODType.Player, MoveType.Navigation, UIType.UnionActor);
            charactor.gameObject.AddComponent<SceneMainActor>();

            var ui = charactor.ui as RCUIUnionActor;

#if UNITY_EDITOR
            var str = "[阵营:" + player.camp + "] #";
            var maxHp = 0.0;
            var curHp = 0.0;
            for(int i=0;i<player.fightInfo.hpPos.Count;++i)
            {
                curHp += player.fightInfo.hpPos[i];
                maxHp += player.fightInfo.maxHpPos[i];
            }

            str += " MaxHP:" + maxHp;
            str += " CurHP:" + curHp;
#endif

			
			ui.Init(name+ str,StaticData.playerData.curTitle,CommonMethod.GetUnionNameByCamp(player.camp), player.serverId);
            ui.SetColor(new Color((float)0xff / (float)0xff, (float)0xe3 / (float)0xff, (float)0x24 / (float)0xff));

            var lod = charactor.lod as RCLODPlayer;
            lod.Init(heroId, weaponId);

            var ai = charactor.ai as RCAIUnionSelf;
            ai.Init(player);
                
            ai.SwitchState((int)UnionActorState.Stand);


            var move = charactor.move as RCMoveNavigation;
            move.SetSpeed((float)Dict.DictDataManager.Instance.tableGameConfigureDao.currentData.UnionFightPlayerMoveSpeed);

            ManagerController.Instance.cameraTool.SetMainPlayer(charactor.transform);
            DoCharactorStart(charactor);
        }

        /// <summary>
        /// 公会战大本营
        /// </summary>
        /// <param name="camp"></param>
        public void CreateUnionBaseCamp(ProtoBuf.Message.InstUFBaseCamp camp)
        {
            var campId = camp.guid+"";

            RoomCharactor charactor = CreateCharactor(campId, CharactorType.UnionFightCamp);
            charactor.Reset(AIType.UnionBaseCamp, LODType.None, MoveType.Fixed, UIType.None);

            var ai = charactor.ai as RCAIBaseCamp;
            ai.Init(camp);

            var pos = Dict.Blo.DictUnionFightBaseCampBlo.GetPosition(camp.id+"");
            var move = charactor.move as RCMoveFixed;
            move.Init(pos, 0);

            DoCharactorStart(charactor);
        }

        public void CreateUnionTower(ProtoBuf.Message.InstUFTower tower)
        {
            var towerId =tower.guid+"";

            RoomCharactor charactor = CreateCharactor(towerId, CharactorType.UnionFightTower);
            charactor.Reset(AIType.UnionTower, LODType.None, MoveType.None, UIType.None);
           
            var ai = charactor.ai as RCAITower;
            ai.Init(tower);
 
            DoCharactorStart(charactor);
        }
        public void CreateUnionChariotFartory(ProtoBuf.Message.InstUFCariotFactory factory)
        {
            var uuid =  factory.guid;
            var dictData = Dict.Blo.DictUnionFightFactoryBlo.GetUnionFightFactoryByID(factory.factoryId+"");
            

            RoomCharactor charactor = CreateCharactor(uuid + "", CharactorType.UnionFightChariotFactory);
            charactor.Reset(AIType.UnionChariotFactory, LODType.None, MoveType.Fixed, UIType.None);

            var ai = charactor.ai as RCAIChariotFactory;
            ai.Init(factory);

            var pos = Dict.Blo.DictUnionFightFactoryBlo.GetPosition(factory.factoryId + "");
            var move = charactor.move as RCMoveFixed;
            move.Init(pos, 0);

            DoCharactorStart(charactor);
        }

        public void CreateUnionChariot(ProtoBuf.Message.InstUFCariot chariot)
        {
            var chariotId = chariot.guid;
            var dictData = Dict.Blo.DictUnionFightCariotBlo.GetUnionFightCariotByID(chariot.cariotId + "");

            RoomCharactor charactor = CreateCharactor(chariotId+"", CharactorType.UnionFightChariot);
            charactor.Reset(AIType.UnionChariot, LODType.UnionChariot, MoveType.Chariot, UIType.UnionChariot);
            var ui = charactor.ui as RCUIUnionChariot;
            ui.Init();
            
            var ai = charactor.ai as RCAIChariot;
            ai.Init(chariot);
            
            var lod = charactor.lod as RCLODUnionChariot;
            lod.Init(dictData.ModelName);

            

            DoCharactorStart(charactor);
        }

        public void CreateUnionRevivePoint(ProtoBuf.Message.InstUFRevivePoint revivepoint)
        {
            var pointId =  revivepoint.guid;

            RoomCharactor charactor = CreateCharactor(pointId+"", CharactorType.UnionFightRevivePoint);
            charactor.Reset(AIType.UnionRevivePoint, LODType.UnionRevivePoint, MoveType.Fixed, UIType.UnionRevivePoint);
          
            var ai = charactor.ai as RCAIRevivePoint;
            ai.Init(revivepoint);

            var ui = charactor.ui as RCUIUnionRevivePoint;
            ui.Init();

            var pos = Dict.Blo.DictUnionFightRevivePointBlo.GetPosition(revivepoint.id + "");
            var move = charactor.move as RCMoveFixed;
            move.Init(pos,0);

            var lod = charactor.lod as RCLODUnionRevivePoint;
            lod.Init(Dict.Blo.DictUnionFightRevivePointBlo.GetUnionFightRevivePointByID(revivepoint.id + ""));

            DoCharactorStart(charactor);
        }

        /// <summary>
        /// 创建守卫
        /// </summary>
        /// <param name="instGuard"></param>
        public void CreateUnionGuard(ProtoBuf.Message.InstUFGuard instGuard)
        {
            var uuid =  instGuard.guid+"";
            RoomCharactor charactor = CreateCharactor(uuid, CharactorType.UnionFightGuard);
            charactor.Reset(AIType.UnionGuard, LODType.UnionGuard, MoveType.Navigation, UIType.UnionGuard);

            var ai = charactor.ai as RCAIGuard;
            ai.Init(instGuard);
            ai.SetCamp(instGuard.camp);

            var lod = charactor.lod as RCLODUnionGuard;

            var dictData = Dict.Blo.DictUnionFightGuardBlo.GetByID(instGuard.UFGuardId);
            lod.Init(dictData);

            var pos = Dict.Blo.DictUnionFightGuardBlo.GetPosition(instGuard.UFGuardId);      

            if (instGuard.initPosition != null)
            {
                 pos = new Vector3(instGuard.initPosition.x, instGuard.initPosition.y, instGuard.initPosition.z);
            }     

            var move = charactor.move as RCMoveNavigation;
            move.MoveTo(pos);


            var ui = charactor.ui as RCUIUnionGuard;
            ui.CreateBoxCollider();
            ui.CreateRigidbody();

#if UNITY_EDITOR
            var str = "[阵营:" + instGuard.camp + "] #";
            var maxHp = 0.0;
            var curHp = 0.0;
            for (int i = 0; i < instGuard.fightInfo.hpPos.Count; ++i)
            {
                curHp += instGuard.fightInfo.hpPos[i];
                maxHp += instGuard.fightInfo.maxHpPos[i];
            }

            str += " MaxHP:" + maxHp;
            str += " CurHP:" + curHp;


            ui.Init(dictData.GuardName + "[uuid]" + uuid + str);
#endif
            var net = RoomManager.currentRoom.netManager as RoomNetUnionFight;
           
            DoCharactorStart(charactor);
        }
        
        /// <summary>
        /// 创建图腾
        /// </summary>
        /// <param name="totem"></param>
        public void CreateUnionTotem(ProtoBuf.Message.InstUFTotem totem,Vector3 pos)
        {
            var uuid = totem.guid+"";
            RoomCharactor charactor = CreateCharactor(uuid, CharactorType.UnionFightTotem);
            charactor.Reset(AIType.UnionTotem, LODType.None, MoveType.SamplePosition, UIType.UnionTotem);

#if UNITY_EDITOR
            var obj = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
            obj.transform.SetParent(charactor.transform);
            obj.transform.localPosition = Vector3.zero;
#endif

            var move = charactor.move as RCMoveSamplePosition;
            move.Init(pos);

            var ai = charactor.ai as RCAIUnionFightTotem;
            ai.Init(totem);
            

            DoCharactorStart(charactor);
        }

        /// <summary>
        /// 创建传输阵
        /// </summary>
        /// <param name="transfer"></param>
        public void CreateUnionTransfer(TableUnionFightTransfer transfer)
        {
            var uuid = transfer.UFTransferId;
            RoomCharactor charactor = CreateCharactor(uuid, CharactorType.UnionFightTransfer);
            charactor.Reset(AIType.UnionTransfer, LODType.None, MoveType.Fixed, UIType.None);
            var ai = charactor.ai as RCAIUnionTransfer;
            ai.Init(transfer);
            
            var move = charactor.move as RCMoveFixed;
            var pos = Dict.Blo.DictUnionFightTransferBlo.GetPosition(uuid);
            move.Init(pos, 0);

            DoCharactorStart(charactor);
        }

        /// <summary>
        /// 工会城门
        /// </summary>
        public void CreateUnionGate(ProtoBuf.Message.InstUFGate gate)
        {
            var gateId = gate.guid+"";

            RoomCharactor charactor = CreateCharactor(gateId, CharactorType.UnionFightGate);
            charactor.Reset(AIType.UnionGate, LODType.None, MoveType.Fixed, UIType.UnionGate);

            var ai = charactor.ai as RCAIGate;
            ai.Init(gate);
            ai.SwitchState((int)UnionGateState.Normal);

            var ui = charactor.ui as RCUIUnionGate;
            //ui.Init(gate);
            
            var pos = Dict.Blo.DictUnionFightGateBlo.GetPosition(gate.id + "");
            //var angle = Dict.Blo.DictUnionFightGateBlo.GetAngle(gate.id + "");
            var move = charactor.move as RCMoveFixed;
            move.Init(pos, 0);

            DoCharactorStart(charactor);
        }

        /// <summary>
        /// 公会角色
        /// </summary>
        /// <param name="id"></param>
        /// <param name="heroId"></param>
        /// <param name="nickname"></param>
        /// <param name="equipId"></param>
        /// <returns></returns>
        public RoomCharactor CreateUnionOther(ProtoBuf.Message.InstUFPlayer player)//...
        {
            var id = player.guid+"";
            var nickname = player.nickName;
            var heroId = player.heroId;
            var weaponId = player.weaponId;
            RoomCharactor charactor = CreateCharactor(id, CharactorType.UnionFightOther);
            charactor.Reset(AIType.UnionOther, LODType.Player, MoveType.Navigation, UIType.UnionActor);

            var ui = charactor.ui as RCUIPlayer;
#if UNITY_EDITOR
            var str = "[阵营:" + player.camp + "] #";
            var maxHp = 0.0;
            var curHp = 0.0;
            for (int i = 0; i < player.fightInfo.hpPos.Count; ++i)
            {
                curHp += player.fightInfo.hpPos[i];
                maxHp += player.fightInfo.maxHpPos[i];
            }

            str += " MaxHP:" + maxHp;
            str += " CurHP:" + curHp;
#endif
            
            ui.Init(nickname+str,player.titleId, CommonMethod.GetUnionNameByCamp(player.camp), player.serverId);
            ui.CreateBoxCollider();
            ui.CreateRigidbody();
            ui.SetColor(Color.white);

            var lod = charactor.lod as RCLODPlayer;
            lod.Init(heroId, weaponId);

            var ai = charactor.ai as RCAIUnionOther;
            ai.Init(player);

            var move = charactor.move as RCMoveNavigation;
            move.SetSpeed((float)Dict.DictDataManager.Instance.tableGameConfigureDao.currentData.UnionFightPlayerMoveSpeed);

            DoCharactorStart(charactor);

            return charactor;
        }

        /// <summary>
        /// 创建怪物
        /// </summary>
        public RoomCharactor CreateUnionMonster(ProtoBuf.Message.InstUFCreep monster,Vector3 pos)
        {
            var uuid = monster.guid + "";
            RoomCharactor charactor = CreateCharactor(uuid, CharactorType.UnionFightMonster);
            charactor.Reset(AIType.UnionMonster, LODType.Player, MoveType.Fixed, UIType.UnionMonster);

            var ai = charactor.ai as RCAIUnionMonster;
            ai.Init(monster);

            var lod = charactor.lod as RCLODPlayer;
            lod.Init(monster.heroId, ""  );

            var move = charactor.move as RCMoveFixed;
            move.Init(pos,0f);

            var ui = charactor.ui as RCUIUnionFightMonster;
            ui.CreateBoxCollider();
            ui.CreateRigidbody();

            DoCharactorStart(charactor);
            return charactor;
        }

        /// <summary>
        /// 创建资源
        /// </summary>
        /// <param name="uuid"></param>
        /// <param name="res"></param>
        public void CreateUnionResource(long uuid,ProtoBuf.Message.InstUFResourcePoint res,Vector3 pos)
        {
            RoomCharactor charactor = CreateCharactor(uuid+"", CharactorType.UnionFightMine);
            charactor.Reset(AIType.UnionMine, LODType.UnionMine, MoveType.Fixed, UIType.UnionMine);

            var dictData = Dict.Blo.DictUnionFightResourceBlo.GetUnionFightResourceByID(res.resourceId);
            var lod = charactor.lod as RCLODUnionMine;
            lod.Init(dictData.ModelName);

            var ui = charactor.ui as RCUIUnionMine;
            ui.CreateBoxCollider();

            var move = charactor.move as RCMoveFixed;
            move.Init(pos, 0);

            var ai = charactor.ai as RCAIUnionMine;
            ai.Init(res);

            DoCharactorStart(charactor);
        }

        /// <summary>
        /// 公会NPC
        /// </summary>
        /// <param name="npc"></param>
        public void CreateUnionNpc(TableUnionFightNpc npc)
        {
            var uuid = "npc_" + npc.UFNId;
            RoomCharactor charactor = CreateCharactor(uuid, CharactorType.UnionFightNpc);
            charactor.Reset(AIType.None, LODType.UnionNpc, MoveType.Fixed, UIType.UnionFightNpc);

            var lod = charactor.lod as RCLODUnionNpc;
            lod.Init(npc);
            

            var ui = charactor.ui as RCUIUnionFightNpc;
            ui.Init(npc);
#if UNITY_EDITOR
            var str = npc.Camp;
#endif
            ui.Init(npc.NPCName+"[阵营 "+str+"]");
            ui.CreateBoxCollider();

            var move = charactor.move as RCMoveFixed;
            move.Init(Dict.Blo.DictUnionFightNpcBlo.GetPosition(npc.UFNId + ""), npc.Angle);
            DoCharactorStart(charactor);
        }

        #endregion

        /// <summary>
        /// 空气墙
        /// </summary>
        /// <param name="airId"></param>
        public void CreateAirWall(string airId)
        {
            var airWall = Dict.Blo.DictCopyAirWallBlo.GetAirWallById(airId);
            CreateAirWall(airWall.BlockId, (float)airWall.BlockX, (float)airWall.BlockY, (float)airWall.BlockZ, (float)airWall.LoadBlock, airWall.BlockRes);
        }
        
        public void CreateAirWall(string id,float x,float y,float z,float a,string blockRes)
        {
            RoomCharactor charactor = CreateCharactor(id, CharactorType.AirWall);
            charactor.Reset(AIType.AirWall, LODType.AirWall, MoveType.Fixed, UIType.None);
            
            var move = charactor.move as RCMoveFixed;

            var pos = new Vector3(x,y,z);
            move.Init(pos,a);

            var ai = charactor.ai as RCAIAirWall;
            ai.Init();

            var lod = charactor.lod as RCLODAirWall;
            lod.Init(blockRes);

            DoCharactorStart(charactor);
        }
        public void CreateResource(string id,string posId)
        {
            bool isFish = false;

            if (id.StartsWith("group_fish_"))
            {
                isFish = true;
            }
            else if (id.StartsWith("group_mine_"))
            {
                isFish = false;
            }

            if (isFish)
            {
                var fish = Dict.Blo.DictFieldResourceBlo.GetOne(id);
                var fishPos = Dict.Blo.DictFieldResourcePosBlo.GetOne(posId);
                var str = id + "@" + posId;
                RoomCharactor charactor = CreateCharactor(str, CharactorType.Fish);
                charactor.Reset(AIType.Fish, LODType.Fish, MoveType.Fixed, UIType.Fish);

                var lod = charactor.lod as RCLODFish;
                lod.Init(fish);

                var ai = charactor.ai as RCAIFish;
                ai.Init(fishPos);

                var ui = charactor.ui as RCUIFish;
                ui.Init(fish,fishPos);
                
                var move = charactor.move as RCMoveFixed;
                var pos = Dict.Blo.DictFieldResourcePosBlo.GetPosition(posId);
                var angle = Dict.Blo.DictFieldResourcePosBlo.GetAngle(posId);
                move.Init(pos, angle);

                DoCharactorStart(charactor);

            }
            else
            {
                var mine = Dict.Blo.DictFieldResourceBlo.GetOne(id);
                var pos = Dict.Blo.DictFieldResourcePosBlo.GetPosition(posId);
                var angle = Dict.Blo.DictFieldResourcePosBlo.GetAngle(posId);
                var str = id + "@" + posId;
                RoomCharactor charactor = CreateCharactor(str, CharactorType.Mine);
                charactor.Reset(AIType.Mine, LODType.Mine, MoveType.Fixed, UIType.Mine);

                var lod = charactor.lod as RCLODMine;
                lod.Init(mine);

                var ui = charactor.ui as RCUIMine;
                var minePos = Dict.Blo.DictFieldResourcePosBlo.GetOne(posId);
                ui.Init(mine,minePos);

                var ai = charactor.ai as RCAIMine;
                ai.Init(minePos);

                var move = charactor.move as RCMoveFixed;
                move.Init(pos, angle);
                /*
                var coll = charactor.gameObject.AddComponent<BoxCollider>();
                coll.center = new Vector3(0, 1, 0);
                coll.size = new Vector3(1, 2, 1);
                */
                DoCharactorStart(charactor);
            }
        }

        public RoomCharactor CreateResourceGuide(string id, string posId)
        {
            bool isFish = false;

            if (id.StartsWith("group_fish_"))
            {
                isFish = true;
            }
            else if (id.StartsWith("group_mine_"))
            {
                isFish = false;
            }

            if (isFish)
            {
                var fish = Dict.Blo.DictFieldResourceBlo.GetOne(id);
                var fishPos = Dict.Blo.DictFieldResourcePosBlo.GetOne(posId);
                var str = id + "@" + posId;
                RoomCharactor charactor = CreateCharactor(str, CharactorType.Fish);
                charactor.Reset(AIType.Fish, LODType.Fish, MoveType.Fixed, UIType.FishGuide);

                var lod = charactor.lod as RCLODFish;
                lod.Init(fish);

                var ai = charactor.ai as RCAIFish;
                ai.Init(fishPos);

                var ui = charactor.ui as RCUIFishGuide;
                ui.Init(fish, fishPos);

                var move = charactor.move as RCMoveFixed;
                var pos = Dict.Blo.DictFieldResourcePosBlo.GetPosition(posId);
                var angle = Dict.Blo.DictFieldResourcePosBlo.GetAngle(posId);
                move.Init(pos, angle);

                DoCharactorStart(charactor);

                return charactor;
            }
            else
            {
                var mine = Dict.Blo.DictFieldResourceBlo.GetOne(id);
                var pos = Dict.Blo.DictFieldResourcePosBlo.GetPosition(posId);
                var angle = Dict.Blo.DictFieldResourcePosBlo.GetAngle(posId);
                var str = id + "@" + posId;
                RoomCharactor charactor = CreateCharactor(str, CharactorType.Mine);
                charactor.Reset(AIType.Mine, LODType.Mine, MoveType.Fixed, UIType.MineGuide);

                var lod = charactor.lod as RCLODMine;
                lod.Init(mine);

                var ui = charactor.ui as RCUIMineGuide;
                var minePos = Dict.Blo.DictFieldResourcePosBlo.GetOne(posId);
                ui.Init(mine, minePos);
                

                var ai = charactor.ai as RCAIMine;
                ai.Init(minePos);

                var move = charactor.move as RCMoveFixed;
                move.Init(pos, angle);

                charactor.gameObject.AddComponent<BoxCollider>();

                DoCharactorStart(charactor);

                return charactor;
            }
        }
        public void CreateRaidHold(ProtoBuf.Message.WorldBossStrongholdInfo info) {
            RoomCharactor charactor = CreateCharactor(info.strongholdId, CharactorType.Stronghold);
            charactor.Reset(AIType.None, LODType.Stronghold, MoveType.Fixed, UIType.Stronghold);

            var ui = charactor.ui as RCUIRaidHold;
            ui.Init(info);

            var move = charactor.move as RCMoveFixed;
            move.Init(info);

            var lod = charactor.lod as RCLODRaidHold;
            lod.Init(info);

            charactor.gameObject.AddComponent<BoxCollider>();

            DoCharactorStart(charactor);
        }

        public void CreateMonster(ProtoBuf.Message.CopyJobInfo monster)//...
        {
            //string model;
            //var dict = Dict.DictDataManager.Instance.tableHeroDao.GetById(data.HeroId);

            TableCopyTask data = new TableCopyTask();
            data.BornAngle = monster.bornAngle;
            data.BornParticleId = monster.bornParticleId;
            data.BornType = monster.bornType;
            data.BornX = monster.bornX;
            data.BornZ = monster.bornZ;
            data.DeadParticleId = monster.deadParticleId;
            data.HeroId = monster.heroId;
            data.IsBoss = monster.isBoss;
            data.PursueR = monster.pursueR;
            data.PursueSpeed = monster.pursueSpeed;
            data.RestTime = monster.restTime;
            data.RotateSpeed = monster.rotateSpeed;
            data.Scale = monster.scale;
            data.SceneName = monster.sceneName;
            data.TaskId = monster.taskId;
            data.ViewR = monster.viewR;
            data.WanderR = monster.wanderR;
            data.WanderSpeed = monster.wanderSpeed;

            RoomCharactor charactor = CreateCharactor(monster.taskId, CharactorType.Monster);
            charactor.Reset(AIType.Monster, LODType.Player, MoveType.Monster, UIType.Player);

            var ai = charactor.ai as RCAIMonster;
            ai.Init(data);

            var lod = charactor.lod as RCLODPlayer;

            lod.Init(data.HeroId,"",(float)data.Scale);

            DoCharactorStart(charactor);
        }

        public void CreateMonster(TableCopyTask task)//...
        {
            RoomCharactor charactor = CreateCharactor(task.TaskId, CharactorType.Monster);
            charactor.Reset(AIType.Monster, LODType.Player, MoveType.Monster, UIType.Player);

            var ai = charactor.ai as RCAIMonster;
            ai.Init(task);

            var lod = charactor.lod as RCLODPlayer;

            lod.Init(task.HeroId, "", (float)task.Scale);

            DoCharactorStart(charactor);
        }



        public void CreateMonster(ProtoBuf.Message.SideMonster sideMonster)//...
        {
            //string model;
            string heroId = "";
            

            var monsters = Dict.DictDataManager.Instance.tableFieldMonsterDao.CacheList;
            foreach(var mon in monsters)
            {
                if(mon.MonId == sideMonster.monId && mon.TeamLeader == 1)
                {
                    heroId = mon.HeroId;
                    break;
                }
            }
            ///兼容
            if (!string.IsNullOrEmpty(sideMonster.heroId))
                heroId = sideMonster.heroId;
            
            var dict = Dict.Blo.DictHeroBlo.GetTableHero(heroId);

#if UNITY_EDITOR
            if(dict==null)
            {
                Debug.Log("[error] heroId:" + heroId+" monsterId:"+sideMonster.monId+" has no leader hero!!!");
            }
#endif

            RoomCharactor charactor = CreateCharactor(sideMonster.uuid, CharactorType.ServerMonster);
            charactor.Reset(AIType.ServerMonster, LODType.Player, MoveType.Navigation, UIType.ServerMonster);
            
            var ai = charactor.ai as RCAIServerMonster;
            //ai.Init(data);
            ai.SwitchState(ServerMonsterAIState.Normal);
            ai.height = (float)dict.Height;
            ai.hpOffest = (float)Dict.DictDataManager.Instance.tableGameConfigureDao.currentData.FieldMonsterHpHeight;

            var lod = charactor.lod as RCLODPlayer;
            lod.Init(heroId, "", (float)dict.ScaleFactor);

            var ui = charactor.ui as RCUIServerMonster;
            ui.Init(sideMonster);
            
           

            //var move = charactor.move as RCMoveServerMonster;
            //move.Init(new Vector3(sideMonster.currentPoint.x, sideMonster.currentPoint.y, sideMonster.currentPoint.z), Random.Range(0,360f));

            DoCharactorStart(charactor);
        }


        public void CreateFieldBoss(ProtoBuf.Message.SideBoss boss)
        {
            //var dataBoss = Dict.Blo.DictFieldBossBlo.GetIndex(boss.bossId);

            var heroId = "";
            var angle = 0f;

            var bosses = Dict.DictDataManager.Instance.tableFieldBossDao.CacheList;
            foreach (var bos in bosses)
            {
                if (bos.BossId == boss.bossId && bos.TeamLeader == 1)
                {
                    heroId = bos.HeroId;
                    angle = (float)bos.BornAngle;
                    break;
                }
            }

            if (!string.IsNullOrEmpty(boss.heroId))
                heroId = boss.heroId;

            var hero = Dict.Blo.DictHeroBlo.GetTableHero(heroId);
            var charactor = CreateCharactor(boss.uuid, CharactorType.FieldBoss);
            charactor.Reset(AIType.FieldBoss, LODType.Player, MoveType.SamplePosition, UIType.FieldBoss);
            var ai = charactor.ai as RCAIFieldBoss;
            ai.Init(boss);
            ai.height = (float)hero.Height;
            ai.hpOffest = (float)Dict.DictDataManager.Instance.tableGameConfigureDao.currentData.FieldMonsterHpHeight;

            ai.SwitchState(FieldBossAIState.Normal);
            var ui = charactor.ui as RCUIFieldBoss;
            ui.Init(boss);
            var lod = charactor.lod as RCLODPlayer;
            lod.Init(heroId, "", (float)hero.ScaleFactor);

            var pos = new Vector3(boss.currentPoint.x, boss.currentPoint.y, boss.currentPoint.z);
            var move = charactor.move as RCMoveSamplePosition;
            //move.Init(pos, angle);
            move.Init(pos);
            move.owner.transform.localRotation = Quaternion.Euler(new Vector3(0, angle, 0));
            DoCharactorStart(charactor);
        }



        #region CreateNPC

        public void CreateNPC(string id)
        {
            var npc = Dict.DictDataManager.Instance.tableNPCDao.GetById(id);
            string npcName = "";
            if (!string.IsNullOrEmpty(npc.nameId))
                npcName = TableTextBlo.GetText(npc.nameId);
            switch (npc.type)
            {
                case (int)NPCType.Normal:
                    CreateNormalNPC(npc.npcId, (float)npc.bornX, (float)npc.bornY, (float)npc.bornZ, (float)npc.bornAngle,
                            npcName, npc.heroId, npc.weaponId, npc.animName, npc.pageName, npc.pageOption, npc.pageLevel, npc.bubbleText, npc.miniMapIcon);
                    break;
                case (int)NPCType.Story:
                    if (npc.necessary > 0 || RenderManager.Quality != RenderLevel.Low)
                    {
                        CreateStoryNPC(npc.npcId, (float)npc.bornX, (float)npc.bornY, (float)npc.bornZ, (float)npc.bornAngle,
                        npcName, npc.heroId, npc.weaponId, npc.animName, npc.bubbleText, npc.miniMapIcon);
                    }
                    break;
                case (int)NPCType.Actor:
                    CreateActorNPC(npc.npcId, (float)npc.bornX, (float)npc.bornZ, (float)npc.bornAngle,
                        npcName, npc.heroId, npc.weaponId, npc.animName, npc.miniMapIcon);
                    break;
                case (int)NPCType.Patrol:
                    if (npc.necessary > 0 || RenderManager.Quality != RenderLevel.Low)
                    {
                        CreatePatrolNPC(npc.npcId, npcName, npc.heroId, npc.weaponId, npc.miniMapIcon);
                    }
                    break;
                case (int)NPCType.Union:
                    CreateUnionNPC(npc.npcId, (float)npc.bornX, (float)npc.bornY, (float)npc.bornZ, (float)npc.bornAngle,
                            npcName, npc.heroId, npc.weaponId, npc.animName, npc.pageName, npc.pageOption, npc.pageLevel, npc.bubbleText, npc.miniMapIcon);
                    break;
            }
        }

        public void CreateNormalNPC(string id, float x,float y, float z, float r, string name, string heroId,string weaponId, string animName, string pageName, string pageOption,int pageLevel,string bubbleText,string iconName)
        {
            RoomCharactor charactor = CreateCharactor(id, CharactorType.NormalNPC);
            charactor.Reset(AIType.NormalNPC, LODType.Player, MoveType.SamplePosition, UIType.NormalNPC);

            var ai = charactor.ai as RCAINormalNPC;
            ai.Init(animName);

            var ui = charactor.ui as RCUINormalNPC;
            string bubble = "";
            if(!string.IsNullOrEmpty(bubbleText))
            {
                bubble = TableTextBlo.GetText(bubbleText);
            }
            ui.Init(name, pageName, pageOption, pageLevel, bubble);
            ui.SetColor(new Color(0, 1, 1));

            var move = charactor.move as RCMoveSamplePosition;
            move.Init(new Vector3(x, y, z));

            var lod = charactor.lod as RCLODPlayer;
            lod.Init(heroId,weaponId);

            charactor.transform.localEulerAngles = new Vector3(0, r, 0);
            charactor.extraInfo = iconName;

            DoCharactorStart(charactor);
        }

        public void CreateUnionNPC(string id, float x, float y, float z, float r, string name, string heroId, string weaponId, string animName, string pageName, string pageOption, int pageLevel, string bubbleText, string iconName)
        {
            RoomCharactor charactor = CreateCharactor(id, CharactorType.NormalNPC);
            charactor.Reset(AIType.NormalNPC, LODType.Player, MoveType.SamplePosition, UIType.UnionNPC);

            var ai = charactor.ai as RCAINormalNPC;
            ai.Init(animName);

            var ui = charactor.ui as RCUIUnionNPC;
            string bubble = "";
            if (!string.IsNullOrEmpty(bubbleText))
            {
                bubble = TableTextBlo.GetText(bubbleText);
            }
            ui.Init(id,name, pageName, pageOption, pageLevel, bubble);
            ui.SetColor(new Color(0, 1, 1));

            var move = charactor.move as RCMoveSamplePosition;
            move.Init(new Vector3(x, y, z));

            var lod = charactor.lod as RCLODPlayer;
            lod.Init(heroId, weaponId);

            charactor.transform.localEulerAngles = new Vector3(0, r, 0);
            charactor.extraInfo = iconName;

            DoCharactorStart(charactor);
        }

        public void CreateStoryNPC(string id, float x,float y, float z, float r, string name, string heroId,string weaponId, string animName, string bubbleText, string iconName)
        {
            RoomCharactor charactor = CreateCharactor(id, CharactorType.StoryNPC);
            charactor.Reset(AIType.NormalNPC, LODType.Player, MoveType.SamplePosition, UIType.StoryNPC);

            var ai = charactor.ai as RCAINormalNPC;
            ai.Init(animName);

            var ui = charactor.ui as RCUIStoryNPC;
            string text = TableTextBlo.GetText(bubbleText);
            ui.Init(name, text);
            ui.SetColor(new Color(0, 1, 1));

            var lod = charactor.lod as RCLODPlayer;
            lod.Init(heroId, weaponId);

            var move = charactor.move as RCMoveSamplePosition;
            move.Init(new Vector3(x, y, z));

            charactor.transform.localEulerAngles = new Vector3(0, r, 0);
            charactor.extraInfo = iconName;

            DoCharactorStart(charactor);
        }

        public void CreateActorNPC(string id, float x, float z, float r, string name, string heroId,string weaponId, string animName, string iconName)
        {
            RoomCharactor charactor = CreateCharactor(id, CharactorType.ActorNPC);
            charactor.Reset(AIType.NormalNPC, LODType.Player, MoveType.Navigation, UIType.Player);

            var ai = charactor.ai as RCAINormalNPC;
            ai.Init(animName);

            var ui = charactor.ui as RCUIPlayer;
            ui.Init(name);
            ui.SetColor(Color.white);
            var lod = charactor.lod as RCLODPlayer;
            lod.Init(heroId, weaponId);

            charactor.transform.position = new Vector3(x, 0, z);
            charactor.transform.localEulerAngles = new Vector3(0, r, 0);
            charactor.extraInfo = iconName;

            DoCharactorStart(charactor);
        }

        public void CreatePatrolNPC(string id,string name,string heroId,string weaponId,string iconName)
        {
            RoomCharactor charactor = CreateCharactor(id, CharactorType.ActorNPC);
            charactor.Reset(AIType.PatrolNPC, LODType.Player, MoveType.Navigation, UIType.Player);

            var ai = charactor.ai as RCAIPatrolNPC;
            ai.Init(id);

            var ui = charactor.ui as RCUIPlayer;
            ui.Init(name);
            ui.SetColor(Color.white);
            var lod = charactor.lod as RCLODPlayer;
            lod.Init(heroId, weaponId);

            charactor.extraInfo = iconName;

            DoCharactorStart(charactor);
        }
        #endregion CreateNPC


        public void CreateArea(Dict.DataModel.TableArea ta)
        {
            string id = ta.areaId;
            RoomCharactor charactor = CreateCharactor(id, CharactorType.Area);
            charactor.Reset(AIType.Area, LODType.None, MoveType.None, UIType.None);
            charactor.extraInfo = ta.miniMapIcon;
            var areaData = Dict.DictDataManager.Instance.tableAreaDao.GetById(id);

            var ai = charactor.ai as RCAIArea;
            ai.Init((float)areaData.range, areaData.pageName, areaData.pageOption,
                new Vector3((float)areaData.resetX, 0, (float)areaData.resetZ));

            charactor.transform.position = new Vector3((float)areaData.bornX, (float)areaData.bornY, (float)areaData.bornZ);

            DoCharactorStart(charactor);
        }

        public void CreateSafeArea(string fieldId)
        {
            var field = Dict.Blo.DictFieldBlo.GetOne(fieldId);
            RoomCharactor charactor = CreateCharactor(field.FieldId, CharactorType.SafeArea);
            charactor.Reset(AIType.SafeArea, LODType.None, MoveType.None, UIType.None);

            var ai = charactor.ai as RCAISafeArea;
            SafeZoneType st = SafeZoneType.Triangle;
            var vec = Dict.Blo.DictFieldBlo.GetSafeZone(field.FieldId, out st);

            ai.Init(vec,st);

            DoCharactorStart(charactor);
        }

        public void CreatePrison(string id)
        {
            RoomCharactor charactor = CreateCharactor(id, CharactorType.Prison);
            charactor.Reset(AIType.Prison, LODType.None, MoveType.None, UIType.None);

            DoCharactorStart(charactor);
        }
        public RoomCharactor CreateCharactor(string id, CharactorType type)
        {
            //Debug.Log("########### create charactor id " +id + " type " +type +"##################");
            if (charactors.ContainsKey(id))
            {
                DestroyCharactor(id);
            }

            RoomCharactor charactor;

            GameObject obj = new GameObject();
            charactor = obj.AddComponent<RoomCharactor>();

            charactor.transform.SetParent(room.transform);
            charactor.name = id.ToString();
            charactor.type = type;
            charactor.charactorManager = this;
            charactors.Add(id, charactor);
            //Debug.Log("[DEBUG] Create Charactor [ID:" + id+"]");
            return charactor;
        }

        public void DestroyCharactor(string id)
        {
            if (charactors.ContainsKey(id))
            {
                var charactor = charactors[id];
                charactors.Remove(id);

                DoCharactorStop(charactor);

                GameObject.Destroy(charactor.gameObject);
            }

        }
        /// <summary>
        /// 加入了新的角色后调用
        /// </summary>
        /// <param name="charactor"></param>
        /// <param name="modelName"></param>
        private void DoCharactorStart(RoomCharactor charactor)
        {
            charactor.DoStart();
            if (onCharactorStartCallback != null)
            {
                onCharactorStartCallback(charactor);
            }
            if (running)
            {
                charactor.DoResume();
            }
        }
        /// <summary>
        /// 在有角色被移除时调用
        /// </summary>
        /// <param name="charactor"></param>
        private void DoCharactorStop(RoomCharactor charactor)
        {
            if (running)
            {
                charactor.DoPause();
            }
            charactor.DoStop();
            if (onCharactorStopCallback != null)
            {
                onCharactorStopCallback(charactor);
            }

        }

        private bool IsCharactorNeedCache(CharactorType type)
        {
            return type == CharactorType.OtherPlayer;
        }

        #endregion
        

    }

}

